#include <shader.h>
Shader::Shader(const string &vertexPath,const string &fragmentPath){
	ifstream vfile(vertexPath),ffile(fragmentPath);
	stringstream vstream,fstream;
	vstream << vfile.rdbuf();
	fstream << ffile.rdbuf();
	vfile.close();
	ffile.close();
	string vertexCode = vstream.str();
	string fragmentCode = fstream.str();

	const char * vertexCodeC = vertexCode.c_str();
	const char * fragmentCodeC = fragmentCode.c_str();

	unsigned int vertex, fragment;
	int success;
	char infoLog[512];
	
	vertex = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertex, 1, &vertexCodeC, NULL);
	glCompileShader(vertex);
	// 打印编译错误（如果有的话）
	checkError(vertex,true);

	fragment = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragment, 1, &fragmentCodeC, NULL);
	glCompileShader(fragment);
	// 打印编译错误（如果有的话）
	checkError(fragment,true);

	ID = glCreateProgram();
	glAttachShader(ID, vertex);
	glAttachShader(ID, fragment);
	glLinkProgram(ID);
	// 打印连接错误（如果有的话）
	checkError(ID,false);

	// 删除着色器，它们已经链接到我们的程序中了，已经不再需要了
	glDeleteShader(vertex);
	glDeleteShader(fragment);
}

void Shader::use(){
	glUseProgram(ID);
}

void Shader::setValue(const string &name,int  value){
	glUniform1i(glGetUniformLocation(ID, name.c_str()), value); 
}

void Shader::setValue(const string &name,float  value){
	glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}

void Shader::setValue(const string &name,bool  value){
	glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}

void Shader::checkError(unsigned int shader,bool isShader){
	GLint success;
    GLchar infoLog[1024];
    if(isShader)
    {
        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
        if(!success)
        {
            glGetShaderInfoLog(shader, 1024, NULL, infoLog);
            cout<<infoLog<<endl;
        }
    }
    else
    {
        glGetProgramiv(shader, GL_LINK_STATUS, &success);
        if(!success)
        {
            glGetProgramInfoLog(shader, 1024, NULL, infoLog);
            cout<<infoLog<<endl;
        }
    }
}

void Shader::setValue(const string &name,const glm::mat4 &value){
	unsigned int transLoc = glGetUniformLocation(ID,name.c_str());
	glUniformMatrix4fv(transLoc,1,GL_FALSE,glm::value_ptr(value));
}

void Shader::setValue(const string &name,const glm::vec3 &value){
	unsigned int loc = glGetUniformLocation(ID,name.c_str());
	glUniform3f(loc,value.x,value.y,value.z);
}